/*
 *  ADomain.cpp
 *  
 *
 *  Created by Peter on 23.02.12.
 *  Copyright 2012 __MyCompanyName__. All rights reserved.
 *
 */

#include "ADomain.h"
#include "AStream.h"
#include "PClassRegistry.h"
#include "AObjDoc.h" /*Currently needed for a hack, reove later!!!*/

A_IMPLEMENT_CLASS( 'DOMN', ADomain, AObject );

void ADomain::writeToStream( AStream& str )
{
	if( !_object.get() )
		throw "Cannot write an empty domain to a stream.";
		
	str.writeString( "Domain" );
	str.writePod( _object->getClassId() );
	
	str.writeString( _object->getClassName() );
	
	// Invoke our serialization mechanism
	_object.get()->writeToStream( str );
}

void ADomain::readFromStream( AStream& str, const AObjDoc& objd )
{
	readFromStream( str );
};


void ADomain::readFromStream( AStream& str )
{
	// TODO: Peek the first 2 bytes to determine endianity
	
	std::string domainHeader = str.readString();
	
	if( domainHeader != "Domain" ) {
		TR_TRACE( "Wrong domain header, expecting \"Domain\", got " << domainHeader );
		throw "Invalid domain header";
	}
	
	// See which object there is in the domain. This is usually 'OBJD'
	// (meaning AObjDoc) for AVB files.
	//
	// NOTE: AObjDoc doesn't seem to be registered with the PClass Registry in
	// Media Composer, but we can do it for now I guess
	AObject::PCID pcid;
	str.readPod( pcid );
	
	if( !PClassRegistry::isClassRegistered( pcid ) )
		throw "Invalid domain key!";
	
	// Create an instance of that class
	_object.reset( PClassRegistry::createInstance( pcid ) );
	
	if( !_object.get() ) {
		TR_TRACE (
			"Failed to creat object instance for class of signature " 
			<< pcidToString( pcid )
		);
		
		throw "createInstance() failed";
	}
	
	std::string domainMagic = str.readString();
	
	if( domainMagic != _object->getClassName() )
	{
		// Great, now we made an object for nothing
		_object.reset( nullptr );
		throw "Inavlid domain magic!";
	}
	
	TR_TRACE( "Domain contains an object of class " << _object.get()->getClassName() << ", reading..." );
	
	// Now have the object do the reading because only it knows how to do it.
	// We don't supply an AObjDoc pointer since we don't have one and don't want
	// one. Stuff that can be saved inside an ADomain must be able to read 
	// itself without an AObjDoc, i.e. it cannot have dependencies on other 
	// objects.
	// FIXME: We should make the AObjDoc argument a pointer, so we can supply 
	// nullptr here without making a dummy AObjDoc!!!!
	AObjDoc dummy; // <- Ugly hack
	_object.get()->readFromStream( str, dummy );
}
